<template>
  <div>
    <vxe-toolbar ref="xToolbar" :custom="custom">
      <template #buttons>
        <Button
          v-for="(item, index) in getLeftButton"
          :key="index + item.permission"
          v-has="item.permission"
          :style="{ float: item.float || 'left', position: 'relative' }"
          style="margin-right: 5px"
          :type="item.type"
          :icon="item.icon"
          :disabled="item.disabled"
          @click="topBtnclick(item)"
        >
          <Spin v-if="item.showSpin" size="small" fix />
          {{ item.name }}
        </Button>
        <Button v-if="showRefresh" icon="md-refresh" @click="handleSearch">
          <span style="margin-left: 5px">刷新</span>
        </Button>
        <div style="line-height: 30px; margin-left: 5px">
          <slot name="otherSearch" />
        </div>
        <slot name="btn" />
      </template>
      <template #tools>
        <Button
          v-for="(item, index) in getRightButton"
          :key="index"
          :style="{ float: item.float || 'left', position: 'relative' }"
          :disabled="!hasPermission(item.permission)"
          style="margin-right: 5px"
          :type="item.type"
          :icon="item.icon"
          @click="topBtnclick(item)"
        >
          {{ item.name }}
        </Button>
        <slot name="right"></slot>
      </template>
    </vxe-toolbar>

    <div class="vxe-table-content">
      <vxe-table
        :id="tableId"
        :ref="tableRef || 'table'"
        size="small"
        sync-resize
        :custom-config="{ resizable: true, storage: tableId ? true : false }"
        :row-config="{ isHover: true, height: 50 }"
        align="left"
        round
        :stripe="stripe"
        :border="border"
        :height="height"
        :loading="loading"
        :data="queryData.records"
        :merge-cells="mergeCells"
        v-bind="$attrs"
        class="internal-table"
        style="margin-top: 10px"
        :sort-config="{ remote: true }"
        v-on="$listeners"
        @sort-change="sortChange"
        @header-cell-click="headerCellClickEvent"
      >
        <!-- @checkbox-change="selectChangeEvent" -->
        <vxe-column
          v-for="config in columns"
          :key="config.key"
          :width="config.width"
          :type="config.type"
          :field="config.key"
          :title="config.title"
          :fixed="config.fixed"
          :filters="config.filters"
          :visible="config.visible"
          :min-width="config.minWidth ? config.minWidth : `${config.type === 'checkbox' ? '60px' : '150px'}`"
          :title-prefix="config.titlePrefix"
          :sortable="config.sortTable"
          show-header-overflow
          show-overflow
          show-footer-overflow
        >
          <template v-if="config.headFormatter || config.header" #header="{ column, columnIndex }">
            <template v-if="config.header">
              <slot :name="config.header" :row="column" :index="columnIndex" :config="config" />
            </template>
            <template v-else>
              <Formatter :callback="config.headFormatter" />
            </template>
          </template>
          <template v-if="config.expand" #content="{ row }">
            <slot :name="config.expand" :row="row" :index="columnIndex" :config="config" />
          </template>
          <template v-if="config.slot" #default="{ row, rowIndex }">
            <span v-if="config.unit">{{ row[config.key] }} {{ config.unit }}</span>
            <span v-if="config.slot === 'date'" slot="date">{{ showDate(row, config.key) }}</span>
            <span v-else-if="config.slot === `${config.key}Date`" :slot="`${config.key}Date`">{{
              showDate(row, config.key)
            }}</span>
            <span v-else-if="config.slot === `${config.key}Datetime`" :slot="`${config.key}Datetime`">{{
              showDatetime(row, config.key, config.looseTime, config.format, config.timeHandler)
            }}</span>
            <span v-else-if="config.slot === `${config.enumsKey}Enums`" :slot="`${config.enumsKey}Enums`">
              <span v-if="config.textOnly">{{ showEnums(row, config.key, config.enumsKey) }}</span>
              <sp-tag
                v-else-if="row[config.key] !== null && row[config.key] !== undefined"
                :use-invert="withTagOption(config, 'useInvert', row)"
                :color="withTagOption(config, 'colors', row)"
                :type="
                  withTagOption(config, 'types', row)
                    || parseTagColor(row, config.key, config.enumsKey, config.tagColorList)
                "
              >
                {{ showEnums(row, config.key, config.enumsKey) }}
              </sp-tag>
              <span v-else />
            </span>
            <span
              v-else-if="config.slot === `${config.key}Price`"
              :slot="`${config.key}Price`"
              style="color: red"
            >{{ `￥${(row[config.key] / 100).toFixed(2) || 0}` }}</span>
            <span
              v-else-if="config.slot === `${config.key}RMB`"
              :slot="`${config.key}RMB`"
              style="color: red"
            >{{ `${(row[config.key] / 100).toFixed(2) || 0}元` }}</span>
            <Poptip
              v-else-if="config.slot === `${config.key}Icon`"
              slot="append"
              transfer
              trigger="hover"
              title="图片预览"
              placement="right"
              width="350"
              style="width: 40px; cursor: pointer"
            >
              <img
                :src="row[config.key]"
                style="width: 100%; margin: 0 auto; display: block; cursor: zoom-in; margin-top: 5px"
                @click="viewImage(row[config.key])"
              >
              <div slot="content">
                <img
                  :src="row[config.key]"
                  style="width: 100%; margin: 0 auto; display: block; cursor: zoom-in"
                  @click="viewImage(row[config.key])"
                >
              </div>
            </Poptip>
            <slot v-else :name="config.slot" :row="row" :index="rowIndex" />
          </template>
          <template v-else-if="config.formatter" #default="{ row }">
            <Formatter :callback="config.formatter" :row="row" />
          </template>
          <!-- <template v-else-if="!config.slot && !config.formatter && !config.type" #default="{ row }">
            <span v-if="row[config.key] === null || row[config.key] === undefined || row[config.key] === ''">-</span>
            <span v-else>{{ row[config.key] }}</span>
          </template> -->
        </vxe-column>
      </vxe-table>
    </div>

    <slot name="extra" />
    <div
      :style="{ justifyContent: !$slots.bottom ? 'flex-end' : 'space-between' }"
      style="display: flex; margin: 10px 0; align-items: center"
    >
      <slot name="bottom" />
      <Page
        v-if="showPage"
        transfer
        :current="searchForm.pageNumber"
        :total="queryData.total"
        :page-size="searchForm.pageSize"
        :page-size-opts="pageSizeOpts"
        size="small"
        show-total
        show-elevator
        show-sizer
        @on-change="changePage"
        @on-page-size-change="changePageSize"
      />
    </div>
  </div>
</template>

<script>
import 'viewerjs/dist/viewer.css'
import Viewer from 'viewerjs'
import ImageUpload from '../imageUpload/index.vue'
import { dateFormat } from '@/libs/dateFmt'
import { typeOf } from '@/shared/Observer'
import { MModal } from '@/components/m-modal/index'
import { pick } from '@/shared'

export default {
  name: 'MTablePlus',
  // eslint-disable-next-line vue/no-unused-components
  components: { ImageUpload, Formatter: () => import('./formatter.vue') },
  props: {
    custom: {
      default: false,
      type: Boolean
    },
    stripe: {
      default: true,
      type: Boolean
    },
    border: {
      default: false,
      type: Boolean
    },
    height: {
      type: [Number, String],
      default: '100%'
    },
    pageSizeOpts: {
      type: Array,
      default () {
        return [15, 20, 30, 50, 100]
      }
    },
    tableRef: String,
    showRefresh: {
      default: false,
      type: Boolean
    },
    draggable: {
      default: true,
      type: Boolean
    },
    showPage: {
      default: true,
      type: Boolean
    },
    // searchData: {
    //     default: () => [],
    //     type: Array
    // },
    tableId: {
      type: String
    },
    columns: {
      default: () => [],
      type: Array
    },
    options: {
      default: () => {},
      type: Object
    },
    btnList: {
      default: () => [],
      type: Array
    },
    btnGroup: {
      default: () => [],
      type: Array
    },
    autoGetData: {
      type: Boolean,
      default: true
    },
    pageForm: {
      type: Object,
      default: () => {
        return {
          pageNumber: 1,
          pageSize: 15
        }
      }
    },
    keep: Boolean,
    mergeCells: {
      default: () => [],
      type: Array
    }

  },
  emits: ['selectChange'],
  data () {
    return {
      searchForm: {
        pageNumber: 1,
        pageSize: 15
      },
      topDateOption: {
        shortcuts: [
          {
            text: '今天',
            value () {
              return [new Date(), new Date()]
            }
          },
          {
            text: '昨天',
            value () {
              const date = new Date()
              date.setTime(date.getTime() - 3600 * 1000 * 24)
              return [date, date]
            }
          },
          {
            text: '最近一周',
            value () {
              const date = new Date()
              date.setTime(date.getTime() - 3600 * 1000 * 24 * 6)
              return [date, new Date()]
            }
          },
          {
            text: '这个月',
            value () {
              const date = new Date()
              date.setDate(1)
              return [date, new Date()]
            }
          }
        ]
      },
      loading: false,
      selectIds: [],
      queryData: {},
      sortData: {}
    }
  },
  computed: {
    showDate () {
      return function (row, key) {
        return row[key] ? dateFormat('YYYY-mm-dd', new Date(row[key])) : ''
      }
    },
    showDatetime () {
      return function (row, key, piko = '', format = 'YYY-mm-dd HH:MM:SS', handler) {
        if (handler) { return handler(row, key, piko, format) }
        return row[key] ? dateFormat(format, new Date(row[key])) : piko
      }
    },
    showEnums () {
      return function (row, key, enumsKey) {
        if (row[key] !== undefined && row[key] !== null) {
          const list = this.getEnums(enumsKey)
          const result = list.find((item) => {
            return item.code === Number.parseInt(row[key])
          })
          return result ? result.name : ''
        } else {
          return ''
        }
      }
    },
    getRightButton () {
      return this.btnList.filter(item => item.float === 'right')
    },
    getLeftButton () {
      return this.btnList.filter(item => item.float !== 'right')
    }
  },
  mounted () {
    if (this.autoGetData) { this.getData() }
  },
  created () {
    this.searchForm = { ...this.pageForm }
  },
  methods: {
    sortChange (v) {
      this.sortData = { order: v.order, sort: v.field }
      this.getData()
    },
    headerCellClickEvent ({ column, triggerResizable, triggerSort, triggerFilter }) {
      if (column.sortable && !triggerSort) {
        const tableRef = this.$refs[this.tableRef || 'table']
        // console.log(column, tableRef, triggerResizable, triggerSort, triggerFilter)
        if (column.order === 'asc') {
          tableRef.clearSort()
          this.sortData = {}
        } else if (column.order === 'desc') {
          tableRef.sort(column.field, 'asc')
          this.sortData = { order: column.order, sort: column.field }
        } else {
          tableRef.sort(column.field, 'desc')
          this.sortData = { order: column.order, sort: column.field }
        }

        this.getData()
      }
    },
    withTagOption (option, key, row) {
      if (!option.tagOptions) { return }
      const maybeInvork = option.tagOptions[key]
      if (typeof maybeInvork === 'function') {
        return maybeInvork(
          { option, row },
          {
            enumHelper: this.getEnums
          }
        )
      }
      return maybeInvork
    },
    parseTagColor (row, key, enumsKey, colors) {
      return this.showTagColor(row, key, enumsKey, colors)
    },
    onDragDrop (first, end) {
      this.$emit('onDragDrop', { first, end })
    },
    viewImage (src) {
      const image = new Image()
      image.src = src
      const viewer = new Viewer(image, {
        hidden () {
          viewer.destroy()
        }
      })
      viewer.show()
    },
    setSelection (selectIds) {
      this.selectIds = selectIds
      this.queryData.records.forEach((item) => {
        if (this.selectIds.includes(item.id)) { item._checked = true }
      })
    },
    modifySelection (selectIds) {
      this.selectIds = selectIds
      this.queryData.records.forEach((item) => {
        if (this.selectIds.includes(item.id)) {
          item._checked = true
          this.$refs[this.tableRef || 'table'].setCheckboxRow(item, true)
        }
      })
    },
    refresh () {
      if (this.keep) {
        const params = {
          ...this.searchForm
        }
        this.getData(params)
        return
      }
      this.handleReset()
    },
    onSelect () {
      this.$emit('on-select', this.searchForm)
    },
    initData () {
      this.getData()
    },
    handleReset () {
      // this.$refs.searchForm.resetFields();
      this.handleSearch()
    },
    handleSearch (params) {
      this.searchForm = {
        ...params,
        pageNumber: 1,
        pageSize: this.searchForm.pageSize || 15
      }
      const p = {
        ...this.searchForm
      }
      this.getData(p)
    },
    changePage (v) {
      this.searchForm.pageNumber = v
      this.getData()
    },
    changePageSize (v) {
      this.searchForm.pageNumber = 1
      this.searchForm.pageSize = v
      this.getData()
    },
    getData (params) {
      this.loading = true
      const p = {
        ...params,
        ...this.searchForm,
        ...this.sortData
      }
      this.$emit('initData', p, (val) => {
        this.loading = false
        this.queryData = val || []
      })
    },
    btnGroupClick (e) {
      this.$emit('btnGroupClick', e)
    },
    getSelection () {
      return this.$refs[this.tableRef || 'table'].getCheckboxRecords()
    },
    expandAllRowEvent () {
      this.$nextTick(() => {
        this.$refs[this.tableRef || 'table'].setAllRowExpand(true)
      })
    },
    async topBtnclick (item) {
      const res = await item.func({ refresh: this.refresh, selected: this.getSelection(), ...pick(item, ['searchData']) })
      if (typeOf(res, 'object') && res.render) { MModal(res) }
    }
  }
}
</script>

<style scoped lang="less">
.ivu-btn {
    border-radius: 10px;
    margin-right: 10px !important;
}
.ivu-btn-del {
    background: none;
    border-color: #f83f52;
    color: #f83f52;
}
</style>
